import fetch from 'isomorphic-fetch';
import qs from 'qs';


/**
 * 调用服务端API的统一函数
 * @param rl 接口 request line, 如 get /oss/es/info
 * @param params 接口参数，如 {period: 2}
 * @param overlay fetch option，任意设置和覆盖已有的 fetch option 配置
 * @param option 如 withToken=true 要求设置鉴权 token
 *
 * in oss
 * Content-Type: application/x-www-form-urlencoded; charset=utf-8
 * /oss//es/info?period=2
 * DcCode: HB01-S003-001
 * Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJkdWxhb2JhbiIsInBob25lIjoiMTMxMjMzNDU0MzIiLCJ1cmxUb2tlbiI6IjN6ODE2QjdhIiwib3JnQ29kZSI6MTAwMDE0LCJyb2xlcyI6WyJPU1NfQURNSU4iLCJST0xFX1NZUyIsIkNNUF9URU5BTlRfQURNSU4iXSwiZXhwIjoxNTk4NDA1Mjk3LCJ1dWlkIjoiZHVsYW9iYW4iLCJlbWFpbCI6ImR1bGFvYkBlbm4uY2IiLCJyZXNvdXJjZUNvZGVzIjpbXSwidXNlcm5hbWUiOiJkdWxhb2JhbiJ9.eIUhQyHufNhSBL0nHC_r2MdFastbAyq2kTCsUor4z6pHMh2auY3NMCB8z2T9INGAHZ2gFTPpLkcMCJ2dld_kTg
 *
 * in portal
 * GET /catalog/menu?appCode=portal&temp=1598429194196
 */
export function callAPI(
  rl: string,
  params: any = {},
  option: any = {},
) {
  const rlsplits = rl.split(/ +/); // 如 !get /catalog/getProduct 拆成
  let method = rlsplits[0].toUpperCase();
  let withToken = true; // 默认发送请求都要带上 token
  const path = rlsplits[1];
  const url1 = `${callAPI.getPortalPath()}${path}`;
  if (method.startsWith('!')) {
    // 如果!开头 request line 则不用请求带 token
    method = method.substr(1);
    withToken = false;
  }
  // console.log({ url1 });

  // 设置 header Content-Type，没有设置则按照 method 设置默认的值
  let { headers } = option;
  if (!headers) {
    option.headers = headers = {};
  }
  if (!headers['Content-Type']) {
    if (method === 'GET' || method === 'URL') {
      headers['Content-Type'] =
        'application/x-www-form-urlencoded; charset=utf-8';
    } else {
      headers['Content-Type'] = 'application/json; charset=utf-8';
    }
  }

  // 如果原来没有该header配置，且 getExtraHeaders 中有，则设置上
  Object.entries(callAPI.getExtraHeaders()).forEach(([key, value]) => {
    if (!headers[key] && value) {
      headers[key] = value;
    }
  });

  // 过渡期，最终删除 callAPI.getExtraHeaders 机制，使用 callAPI.getToken 机制
  if (withToken && callAPI.getToken) {
    headers.Authorization = `Bearer ${callAPI.getToken()}`;
  }

  // 如果不需要 token，且获得了 Authorization，则清除掉
  // 如果设置了 headers.Authorization，内容只有 Bearer 则由 devproxy 自动填补
  if (!withToken && headers.Authorization) {
    delete headers.Authorization;
  }

  // 数据在 query 或 body 中
  let url2;
  let body; // fetch option.body
  if (method === 'GET' || method === 'URL') {
    const query = qs.stringify({...params, ...callAPI.getExtraQuery()});
    url2 = query ? `${url1}?${query}` : url1;
  } else {
    url2 = url1;
    body = JSON.stringify(params);
  }
  // console.log({ url2 });

  // url 添加 temp 参数，模仿 portal 调用后台现状，但是发现不用也可以
  // const urlParsed = new URI(url2);
  // urlParsed.addQuery('temp', Date.now());
  // const fetchUrl = urlParsed.href();
  // console.log({ fetchUrl, method, body, option });

  const responsePromise = fetch(url2, {
    method,
    body,
    ...option,
  });
  // onResonse 处理 promise，有机会实现超时检测等功能；如果直接返回 promise 结果就没机会检测超时了。
  return callAPI.onResponse(responsePromise);
}

export { callAPI as callApi };


callAPI.getPortalPath = () => {
  return '';
};

// 通常这些 header 项来自前端应用全局状态
// 经常设置以下 header
// 1. Bearer token 登录令牌
// 2. DcCode 区域编码
// 3. isvFlag 是否独立服务商角色访问
callAPI.getExtraHeaders = () => ({});

// 通常这些 url query 项来自前端应用全局状态
// 经常设置以下 query
// 1. 类似 urlToken=rnU2cJ06
callAPI.getExtraQuery = () => ({});

// 自行设置响应处理函数，返回 promise
callAPI.onResponse = (resp: Promise<Response>) => resp.then((res) => res.json());

callAPI.getToken = () => '';

export default callAPI;


/*
ucenter/api/current-user/authority-trees/oss?authorityType=2
{
  "content" : [ ],
  "resultCode" : 1,
  "errorCode" : null,
  "errorMessage" : null,
  "errorLevel" : null
}
*/

export function responseStandardize(resp: any) {
  if (resp.errorCode) {
    // errorCode: 0
    // errorLevel: null
    // errorMessage: ""
    return {
      o: false,
      e: true,
      c: resp.resultCode | resp.status, // 设置方法来自 common-frontend-tools
      m: resp.errorMessage || resp.msg || resp.errorMsg, // 设置方法来自 common-frontend-tools
      E: {
        errorCode: resp.errorCode,
        errorMessage: resp.errorMessage,
        errorLevel: resp.errorLeve,
      }
    }
  } else {
    // resultCode: 1
    // resultMessage: "SUCCESS"
    return {
      o: true,
      e: false,
      c: resp.resultCode,
      m: resp.resultMessage,
      // 参考原版 const getBodyContent = ({ data: { content, result, results } = {} }) => content || result || results;
      d: resp.content || resp.result || resp.results,
    }
  }
}
